package com.study.it.dubbo;

import com.codingapi.tx.annotation.TxTransaction;
import com.study.it.dubbo.face.AccountDubbo;
import com.study.it.dubbo.face.RecordDubbo;
import com.study.it.entity.Account;
import com.study.it.entity.Record;
import com.study.it.hystrix.command.DubboCommand;
import com.study.it.service.RecordService;
import com.study.it.util.LoadUtil;
import org.hibernate.Hibernate;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
@Service("recorddubbo")
public class RecordDubboImpl implements RecordDubbo {
    @Autowired
    private RecordService service;
    @Autowired
    @Qualifier("accountDubboService")
    private AccountDubbo accountDubboService=null;

    @Transactional(readOnly = true)
    @Override
    public List<Record> findListByAccountId(Integer accId) {
        DetachedCriteria dc=DetachedCriteria.forClass(Account.class);
        dc.add(Restrictions.eq("account.id",accId));
        List<Record> list= service.findList(dc);

        //LoadUtil.init(list);
        //        for(Record r:list)
        //        {
        //            if(! Hibernate.isInitialized(r.getAccount()))//是否还没取出来
        //                Hibernate.initialize(r.getAccount());//人工强制取出来
        //
//        }
        return list;

    }

    @Transactional(readOnly = true)
    @Override
    public List<Record> findListByCardNo(String cardNo) {
        DetachedCriteria dc=DetachedCriteria.forClass(Record.class,"r");
        //dc.createCriteria("r.account","a");
        //dc.add(Restrictions.eq("a.cardNo",cardNo));
        List<Record> list= service.findList(dc);
        //System.out.println(list.get(0).getAccount().getCardNo());
        //LoadUtil.init(list);

        return list;
    }


    @Transactional(readOnly = true)
    @Override
    public Record findOneById(Integer id) {
        Record r= service.findOne(id);
        //LoadUtil.init(r);
        return r;
    }

    @Transactional
    @TxTransaction//配角这样写(不是事务的开端)
    @Override
    public Record add(Float money, String cardno) {
        Record r = new Record();
        r.setMoney(money);
        r.setOprTime(new Date());
        r.setAccount(this.accountDubboService.findByCardNo(cardno));
        service.add(r);
        //LoadUtil.init(r);
        return r;
    }

    @Transactional
    @TxTransaction//配角这样写(不是事务的开端)
    @Override
    public Record add(Float money, Integer accountId) {
//        try {
//            Thread.sleep(10000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        Record r=new Record();
        r.setMoney(money);
        r.setOprTime(new Date());
        Account ac=new Account();
        ac.setId(accountId);

        r.setAccount(ac);
        service.add(r);
        return r;
    }

    @Override
    @TxTransaction(isStart = true)//主角加上这两句(事务的开端)
    @Transactional
    public Record take(Float money, String cardno) {

        DubboCommand<Account> cmd = new DubboCommand<Account>(
                this.accountDubboService
                , "editMoney"
                , new Object[]{cardno, -Math.abs(money)}
                , null);
        Account ac = cmd.execute();
        if(ac==null)
            throw new RuntimeException("远程调用出错");

        Record r=this.add(-Math.abs(money),cardno);
        //this.accountDubboService.editMoney(cardno,-Math.abs(money));
        return r;

    }

    @TxTransaction(isStart = true)//主角加上这两句(事务的开端)
    @Transactional
    @Override
    public Record take(Float money, Integer accountId) {
        Record r=this.add(-Math.abs(money),accountId);
        DubboCommand<Account> cmd = new DubboCommand<Account>(
                this.accountDubboService
                , "editMoney"
                , new Object[]{accountId, -Math.abs(money)}
                , null);
        Account ac = cmd.execute();
        if(ac==null) {
            System.out.println("远程调用出错");
            //要抛出异常才能让分布式事务回顾
            throw new RuntimeException("远程调用出错");
        }


        //this.accountDubboService.editMoney(accountId,-Math.abs(money));
        return r;
    }

    @TxTransaction(isStart = true)//主角加上这两句(事务的开端)
    @Transactional
    @Override
    public Record save(Float money, String cardno) {
        Record r=this.add(money,cardno);
        DubboCommand<Account> cmd = new DubboCommand<Account>(this.accountDubboService,"editMoney", new Object[]{cardno, Math.abs(money)}, null);
        Account ac = cmd.execute();
        if(ac==null)
            throw new RuntimeException("远程调用出错");
        //this.accountDubboService.editMoney(cardno,money);
        return r;
    }

    @TxTransaction(isStart = true)//主角加上这两句(事务的开端)
    @Transactional
    @Override
    public Record save(Float money, Integer accountId) {
        Record r=this.add(money,accountId);
        DubboCommand<Account> cmd = new DubboCommand<Account>
                (this.accountDubboService,"editMoney", new Object[]{accountId, Math.abs(money)}, null);
        Account ac = cmd.execute();
        if(ac==null)
            throw new RuntimeException("远程调用出错");
        return r;
    }

    @TxTransaction
    @Transactional
    @Override
    public Record edit(Record o) {
        service.edit(o);
        return o;
    }

    @TxTransaction(isStart = true)
    @Transactional
    @Override
    public Record editRecord(Record o) {
        service.edit(o);
        return o;
    }

    @TxTransaction
    @Transactional
    @Override
    public Integer remove(Integer id) {
        service.remove(id);
        return 1;
    }
}
